using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;
using System.Web.UI;
using System.Web;
using System.Web.UI.WebControls;
using System.ComponentModel;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Publishing;
using Microsoft.SharePoint.WebPartPages;

namespace RandomFlashMovieWebPart
{
    
   /// <summary>
    /// This WebPart is inspired in the Random Flash Movie Control by CroweMan with could be found in the gotdotnet site.
    /// The RandomFlashMovieWebPart will allow an author to select one or more flash movies from the resource gallery. 
    /// One of the movies will be randomly displayed when the user is in presentation mode.
   /// </summary>
    [DefaultProperty("ImagesList"),
     Description("The Random Flash Movie WebPart will allow an author to select one or more flash movies from the resource gallery. One of the movies will be randomly displayed when the user is in presentation mode."),
     ToolboxData("<{0}:RandomFlashMovieWebPart runat=server></{0}:RandomFlashMovieWebPart>"),
           XmlRoot(Namespace = "RandomFlashMovieWebPart.RandomFlashMovieWebPart")]
    public class RandomFlashMovieWebPart : WebPart
    {
        
        /// <summary>
        /// This is the MARKUP that is generated to display the flash movie
        /// </summary>
        const String FLASH_MARKUP =
"<object classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"" +
"codebase=\"http://active.macromedia.com/flash4/cabs/swflash.cab#version=4,0,0,0\"" +
"WWW HHH>" +
"<param name=\"movie\" value=\"XXX\"> " +
"<param name=\"quality\" value=\"high\">" +
"<param name=\"bgcolor\" value=\"#FFFFFF\">" +
"<embed src=\"XXX\" " +
"quality=\"high\" " +
" bgcolor=\"#FFFFFF\" " +
" WWW " +
" HHH " +
"type=\"application/x-shockwave-flash\" " +
"pluginspage=\"http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash\"> " +
" </embed> " +
" </object> ";

        /// <summary>
        /// Empty Contructor
        /// </summary>
        public RandomFlashMovieWebPart()
        {

        }

        string myImagesList;

        /// <summary>
        /// To get a list of images a SharePoint Document Library must be specified.
        /// This property is edited using a ToolPart that populates a list of Sharepoint Document Libraries
        /// </summary>
        [Browsable(false),
         FriendlyName("Videos Document Library"),
         Description("This is the document list that holds the flash movies"),
         WebPartStorage(Storage.Personal)]
        public string ImagesList
        {
            get { return myImagesList; }
            set { myImagesList = value; }
        }

        string myImagesNames;

        /// <summary>
        /// For a given SharePoint Document Library a list of one or more images must be specified
        /// </summary>
        [Browsable(false),
         FriendlyName("Random Flash Videos"),
         Description("This is the list of videos to randomly change"),
         WebPartStorage(Storage.Personal)]
        public string ImagesNames
        {
            get { return myImagesNames; }
            set { myImagesNames = value; }
        }




        /// <summary>
        /// Render this Web Part to the output parameter specified.
        /// </summary>
        /// <param name="output"> The HTML writer to write out to </param>
        protected override void Render(HtmlTextWriter output)
        {
            
            if (string.IsNullOrEmpty(ImagesList))
            {
                output.Write("This WebPart will randomly display flash videos from a Document Library, please specify one.");
                return;
            }
            if (string.IsNullOrEmpty(ImagesNames))
            {
                output.Write("Please select the videos you want to randomly display.");
                return;
            }


            SPList list = Utils.GetListByPath(ImagesList);
            SPDocumentLibrary documentLibrary = list as SPDocumentLibrary;
            if (documentLibrary == null)
                output.Write("Sorry! you must first indicate a name for an SharePoint Document Library where the flash movies are stored.");
            else
            {
                if (ImagesNames == null)
                    output.Write("Please select one or more movies that you what to be randomly selected and rendered in this control");
                else
                {
                    EnsureChildControls();
                    //Create a table
                    output.RenderBeginTag("table");
                    output.RenderBeginTag("tr"); //Add a row
                    output.RenderBeginTag("td"); // Add a cell
                    if (ImagesList != null && ImagesNames != null)
                    {
                        string[] images = ImagesNames.Split(',');
                        int size = images.Length;
                        Random random = new Random();
                        int selectedImage = random.Next(size);
                        //First create a markup that points to the image
                        string markup = FLASH_MARKUP.Replace("XXX", SPContext.Current.Web.Url + "/" + ImagesList + "/" + images[selectedImage]);
                        if (!string.IsNullOrEmpty(Width))
                            markup = markup.Replace("WWW", " width=\"" + this.Width + "\"");
                        if (!string.IsNullOrEmpty(Height))
                            markup = markup.Replace("HHH", " height = \"" + this.Height + "\"");

                        output.Write(markup);
                    }
                    output.RenderEndTag(); //End of the cell tag
                    output.RenderEndTag(); //End of the row tag
                    output.RenderEndTag(); //End of table tag
                }
            }

        }
        
        /// <summary>
        /// We override this method to add a ToolPart where the user can select a document library and indicate the movies he/she wants.
        /// </summary>
        /// <returns></returns>
        public override ToolPart[] GetToolParts()
        {
            ToolPart[] toolParts = new ToolPart[2];
            
            //** The first ToolPart is our own created RandomFlashMovieToolPart
            //** The WebPartToolPart class represents a ToolPart 
            //that can be used to show or modify web part base properties  like the minimize and title properties.

            toolParts[0] = new RandomFlashMovieToolPart();
            toolParts[1] = new WebPartToolPart();
            return toolParts;
        }



    }

    /// <summary>
    /// Provides a Web Interface that consist of a dropdown that shows the document libraries available
    /// and one the document library has been selected, populates a list with the flash movies and lets the user select which 
    /// will be randomly selected.
    /// </summary>
    public class RandomFlashMovieToolPart : ToolPart
    {
        private Literal message = null;
        private ListBox listMovies = null;
        private DropDownList ddlList = null;

        /// <summary>
        /// The drowndown list will be created an initialized in the constructor. The DropDownList is filled with the list of available Lists
        /// </summary>
        public RandomFlashMovieToolPart()
        {
            this.Title = "Random Flash Video Settings";
        }


        /// <summary>
        /// The controls are created and initialized here
        /// </summary>
        protected override void CreateChildControls()
        {
            ddlList = new DropDownList();
            ddlList.AutoPostBack = true;
            listMovies = new ListBox();
            listMovies.SelectionMode = ListSelectionMode.Multiple;
            ddlList.ID = "ddlLists";
            message = new Literal();
            message.Text = "Please choose a Document list to select the images:";
            Controls.Add(message);
            Controls.Add(ddlList);
            Controls.Add(listMovies);
            SPWeb currentWeb = SPContext.Current.Site.RootWeb;
            AddLists(currentWeb.Url, currentWeb, ddlList);
            ddlList.SelectedIndexChanged += new EventHandler(ddlList_SelectedIndexChanged);
            RandomFlashMovieWebPart webPart = ParentToolPane.SelectedWebPart as RandomFlashMovieWebPart;
            ddlList.SelectedValue = webPart.ImagesList;
            //For the selected list we must load all the available movies
            LoadMoviesList(ddlList.SelectedValue);
            UpdateSelectedMovies(webPart);

        }

        /// <summary>
        /// Fills the list with all the document libraries it can find starting from the given web
        /// </summary>
        /// <param name="removePrefix">Removes this prefix form the title used in listitems</param>
        /// <param name="web"></param>
        /// <param name="ddlList"></param>
        protected void AddLists(string removePrefix, SPWeb web, DropDownList ddlList)
        {
            foreach (SPList list in web.Lists)
            {
                if (list is SPDocumentLibrary)
                {
                    String myUrl;
                    //We format a path string that represents the location of the list
                    if (list.ParentWebUrl.Equals("/"))
                        myUrl = "/" + list.Title;
                    else
                        myUrl = list.ParentWebUrl + "/" + list.Title;
                    if (list.ParentWebUrl.Equals(removePrefix))
                    {
                        myUrl = "/" + list.Title;
                    }
                    if (PublishingWeb.GetPagesListId(web).Equals(list.ID))
                    {
                        //skip. We wont add Pages List
                    }
                    else
                    {
                        String itemTitle = myUrl.Replace(removePrefix, "");
                        ddlList.Items.Add(new ListItem(itemTitle, itemTitle));
                    }
                }
            }
            foreach (SPWeb childWeb in web.Webs)
            {
                AddLists(removePrefix, childWeb, ddlList);
            }


        }

        /// <summary>
        /// When this event is triggered the list of movies is updated
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void ddlList_SelectedIndexChanged(object sender, EventArgs e)
        {
            LoadMoviesList(ddlList.SelectedValue);
        }

        private void LoadMoviesList(String listName)
        {
            SPList flashMoviesList = Utils.GetListByPath(ddlList.SelectedValue);
            listMovies.Items.Clear();
            foreach (SPListItem flashMovie in flashMoviesList.Items)
            {
                if (flashMovie.Name.ToLower().EndsWith("swf"))
                    listMovies.Items.Add(new ListItem(flashMovie.Name));
            }
        }




        /// <summary>
        /// We have to render the DropDownList to the client by overloading the RenderToolPart. 
        /// We first retrieve the selected web part. 
        /// Because this ToolPart belongs to the RandomFlashMovieWebPart we can cast it to this class.
        /// The property ImageList of the RandomFlashMovieWebPart is used for getting the currently selected ImagesList. 
        /// The property ImageNames of the RandomFlashMovieWebPart is used for getting the currently selected movies. 
        /// </summary>
        /// <param name="output"></param>
        protected override void RenderToolPart(HtmlTextWriter output)
        {
            EnsureChildControls();
            if (!Page.IsPostBack)
            {
                RandomFlashMovieWebPart webPart = ParentToolPane.SelectedWebPart as RandomFlashMovieWebPart;
                if (webPart.ImagesList != null)
                {
                    ddlList.SelectedValue = webPart.ImagesList;
                }
                UpdateSelectedMovies(webPart);
            }
            output.RenderBeginTag("table");
            output.RenderBeginTag("tr"); //Add a row
            output.RenderBeginTag("td"); // Add a cell
            message.RenderControl(output);
            output.RenderEndTag();//closes cell
            output.RenderEndTag();//closes row


            output.RenderBeginTag("tr"); //Add a row
            output.RenderBeginTag("td"); // Add a cell
            ddlList.RenderControl(output);
            output.RenderEndTag();//closes cell
            output.RenderEndTag();//closes row


            output.RenderBeginTag("tr"); //Add a row
            output.RenderBeginTag("td"); // Add a cell
            listMovies.RenderControl(output);
            output.RenderEndTag();//closes cell
            output.RenderEndTag();//closes row

            output.RenderEndTag();//close table

        }

        private void UpdateSelectedMovies(RandomFlashMovieWebPart webPart)
        {
            if (webPart.ImagesNames != null)
            {
                string[] names = webPart.ImagesNames.Split(',');
                foreach (String s in names)
                {
                    foreach (ListItem l in listMovies.Items)
                    {
                        if (l.Text.Equals(s))
                        {
                            l.Selected = true;
                        }
                    }
                }
            }
        }

        /// <summary>
        /// We override the ApplyChanges for storing the data back into the RandomFlashMovieWebPart 
        /// Here we set the ImagesList and ImagesName propertues 
        /// </summary>
        public override void ApplyChanges()
        {
            RandomFlashMovieWebPart webPart = ParentToolPane.SelectedWebPart as RandomFlashMovieWebPart;
            webPart.ImagesList = ddlList.SelectedValue;
            string strImagesNames = GetSelectedValues(listMovies);
            webPart.ImagesNames = strImagesNames;

        }


        /// <summary>
        /// Returns all the selected values concatenated as a 
        /// string so it can be passed to the WebPart
        /// </summary>
        /// <param name="list"></param>
        /// <returns></returns>
        protected string GetSelectedValues(ListBox list)
        {
            StringBuilder sb = new StringBuilder();
            int count = 0;
            foreach (ListItem item in list.Items)
            {
                if (item.Selected)
                {
                    if (count > 0) sb.Append(",");
                    sb.Append(item.Value);
                    count++;
                }
            }
            return sb.ToString();
        }


    }

    class Utils
    {
        static public SPList GetListByPath(string path)
        {
            SPContext spc = SPContext.Current;
            if (path.StartsWith("/"))
                path = path.Substring(1);
            SPWeb theWeb = spc.Site.RootWeb;
            String[] pieces = path.Split('/');
            for (int i = 0; i < pieces.Length - 1; i++)
            {
                theWeb = theWeb.Webs[pieces[i]];
            }
            if (theWeb == null)
                return null;
            else
                return theWeb.Lists[pieces[pieces.Length - 1]];
        }
    }



}
